{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Equation solving tools\n", "\n", "We distinguish between root finding or solving algebraic equations and solving differential equations.\n", "\n", "It is also useful to distinguish between approximate solution using numeric methods and exact solution." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exact solution using sympy\n", "\n", "We can solve systems of equations exactly using sympy's `solve` function. This is usually done using what is known as the residual form. The residual is simply the difference between the LHS and RHS of an equation, or put another way, we rewrite our equations to be equal to zero:\n", "\n", "\\begin{align}\n", "x + y &= z \\\\\n", "\\therefore x + y - z &= 0\n", "\\end{align}" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import sympy\n", "sympy.init_printing()\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "x, y, z = sympy.symbols('x, y, z')" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAADgAAAAVBAMAAADhmjDFAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQQq1SZZiK7ze+VntzDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA3UlEQVQoFWMQUmbAAYAyrjikgMKu1JJkXYBsCZqxHAKkSSaKJ7s0gLXAdCZOZGArgLh2AmMhpwKKpEMfA9cHsCTXBsbf7AuQJbkb5jKwHwBLMjPwXABJcSop6T1SUipgYGBjeMjAJwAxloEf5kiYnazfGOwNoJLxG9gSkI1l4LzAIAcJvpyAegYWsBwDTCdPAcNxiGS/2TyGCFRJzgLWXxDJTEGOWQ2okmwlkr8hkhBxMAkzloGBBegBtLBlXQBROZchrwFDEiLFwKDIUAJkoumESTZKBoAlnXCnoacAi9ItRLIhYqcAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left [ x + y\\right ]$$" ], "text/plain": [ "[x + y]" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.solve(x + y - z, z)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can solve systems of equations using `solve` as well, by passing a list of equations" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "equations = [x + y - z, \n", " 2*x + y + z + 2,\n", " x - y - z + 2]\n", "unknowns = [x, y, z]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPUAAAAyBAMAAAB2coBaAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAIrt2EIlmRJmrMu/dzVR9PQywAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADd0lEQVRYCcVYz2sTQRR+aTZukrab4B+gvYmIuFIEBSELemihpaHiUbu9eFMLHi00qKCixVJF7MmgeNFCqx6k0tqLF0uFgFehOQpeav2BFLXum53ZzG4mk5l02zzK7PvxzfdlMm920wXwbG8PjrtoL2wmltxwmLtLV3MxT5VGXJlktiSr6tay78mMwZf+RPO3lKBrSlrWK/ZP/iATjFf+vI516fyTcWpD0teGkTIRzfXItLMXd0R7ziaiQ1LyVLe0LPvYohpb9/6Sr+1fREgvd3RntId8UXoRayfc9mmnoH3ao+3TTtjt0zZnZh4vFMWt0FKW9blKrwF07sgZU9OW33p0F6+17vTahq0r0BifOfTnPqmqrbsxUVCZdQJX1YlJ23i01jZtgEIL2n4Hz237DLWgTTu4MKa6SY1wLWh3rxOyRRyN3gfPzqPTVcJRbsZxG/oRQsEi7dmVhFtDIDhk1i8M0+SnUxpO2HcxHKrgKLeUNQ+XEULBIu1Pw8c5RD3fvbyXu1PGwigU8g/RMXBoYvvSFZhGDAULtBMOFDlEPWH6DcBAieTLcJivD66irUBuC42voO902vCaSwq0AfqcAGF8JnTlEN1XGwZuUMj3ANrcmXCymxxKpJ0gy+ZAUXfcZt85mN/gdLTcMJ6E5DxXFGlfYRvC4Xg3/daLSK8ZBzLr/gbx9Zrv1Fz0DkLHFJdBbe+PN9OFDB/X+f6P5I9e3trsmzerCBD2ufEXSzW7DRMuRrU+jyKeDB9b4RDohswkZwzw3mJct79cIkXx+V51QjP7z5AjQs/39PIHGyKIorXk0QZ3gNBsDOg/JNJ7auLsNeSwHJzA2TnOJ24dIgogMaUDyFVITB9nQiz0wZ5/XiUVqqYrxrtQog4RrbKY0nm7NUVSUu1ClezkKTaZXLvsTDGU8IIwIlplMaXztEskJdW+OgbYZy5BssHqvcnc4OoGnsyhdGra3lb7HSlj1KlROpV1A4y7OtRNsZROSfvpTLkpnwaA0Slpg4V9Hp9ROjVtWHbiU/aYfDoV7ecAR6rxaQd0CtrGlhOndo1OQRsW2JcUz9oDOqbt397E5BfiPd8BnYq2eYs8S8QfTD8b0NF3PbkefY5tz6APzw76um3bfDoEhTJBZ3/qTIoHayxRnpFqPIQaLOxdLiTlL3M1KFWh5mqeQdv07v4/QbnspQ26N2oAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left \\{ x : - \\frac{4}{3}, \\quad y : 1, \\quad z : - \\frac{1}{3}\\right \\}$$" ], "text/plain": [ "{x: -4/3, y: 1, z: -1/3}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solution = sympy.solve(equations, unknowns)\n", "solution" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "13.5 ms ± 4.97 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%%timeit\n", "sympy.solve(equations, unknowns)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the result is a [dictionary](https://docs.python.org/3/tutorial/datastructures.html#dictionaries). We can get the individual answers by indexing (using [])" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAB0AAAAqBAMAAAC9wk0pAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEM3dMpmrdmaJIkTvu1QvnDACAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAn0lEQVQoFWNgQAKuSGwQ0wyVz47G91BDlZ+AymdfgMpfwYDKn4DK51iAyl/OgMrflpb2JxPVwmOoXIa/qPyg/9dRBQaCJ2QMAiYMDP9B4AMNnbBy6m1k0xkDGPofIAmw/2OQV0Dic59m4EfmA6XeNyDJMzBwW6BwWcpSUPhA9Q9QBXg+IvFZHBh4/yHx5T+i8nkSGFDUczSg2b81FOgfAG0gJ/gzPumOAAAAAElFTkSuQmCC\n", "text/latex": [ "$$- \\frac{4}{3}$$" ], "text/plain": [ "-4/3" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solution[x]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We often need the numeric value rather than the exact value. We can convert to a floating point number using `.n()`" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAK8AAAAOBAMAAACr/FENAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAEM3dMquZdrvvIolEZlQyeDuZAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABTElEQVQ4EX2UsUrDYBSFTzBSK2ktgq7JK4iuQgfB1UFxLR2KL+DsLAid3AQfwN3FpSAIbn0BMT5BaZ2N/rlNck5vwX/4uJzvzxkuPwHqEx/YtP1yNYEDnp7vIKCW0O6IqXv3hnMb99Ep4BAN8JkTohnaJKbuBVrL4ps8WsChVSDNCNEMbRKzVvw+wQIOyQN2MkI0Q5vErBUD3Z8QOmA2DSFBLaFpMVV3tQrgtexwSI5DRohmaJOYqrfeMU4v+vCIr88BQjRDm8TUvU0xukXIHDDLQ0hQS2i6MbuH5TlqXkX4/rG3jnb5Zgi5w9AmMeGL8lQ7PgHGuUPcx1ZBgJqhTWKWpSyOfnsYf60iT+ehmOCdf4wvxn25Cof2WdgCIXcY2iRmtTjN8FE+YYfONLxWQjRDm8Q0xZu335fYGCAZhZ+QA95G4SdEUEtomuYPeBM9InVIvrcAAAAASUVORK5CYII=\n", "text/latex": [ "$$-1.33333333333333$$" ], "text/plain": [ "-1.33333333333333" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solution[x].n()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Special case: linear systems\n", "\n", "For linear systems like the one above, we can solve very efficiently using matrix algebra. The system of equations can be rewritten in matrix form:\n", "\n", "$$ A\\mathbf{x} = \\mathbf{b}$$" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZEAAAAVBAMAAAB1Wc4eAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQQq1SZZiK7ze+VntzDAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADZ0lEQVRYCd1WO2gUURQ9m/1nkhglKGkkTgpJo4uIlZAlaBdw7cTGCVYBlTUE22zAOq4WygqRbe2CiKI2BgXbVbAT/PTGiJjCENaZ9+59776ZrLu6lXnFvHvP3HPuPfPZWRyYxB5YKb+Es3vAR2ghU+nLybPVV/98Hfrhuk29xodSn068Ks5VXNWes364sSZPkfmZcJJtxqr+mOYDjHySFRdlouKOSIKboHYHSPwGsJFwUhjtzrcVI1vIb9sUWJaJijsiCW6C2h0g8W8Bltbi78nfOclPIP9DNuw4tyiimgRXlPQaktQCsFTSTuYOXT5TU3R2MncbuaoreGLSa7pIlA1swrL5ngg2e0v7peeazYjixgSFFJ0RUlxrB7FSx+npqqeuFydUITspr2Bwk6l6fzs77gIqmx6FZbMTweZmw2PrdU1nBAi5sSWk6IyQ4lo7iJFKf9dOBtdS2/mmKiQnXm0V+ZdMVbsXoOwAOpmCYJMTyeZmT5AhNiPAVFxPSulzUoqqxSBGaqCunaQx1IrKir5/7IvvV4EcPmMkvGK5d360SkpkPlCbcyjWwWzc8f0N3z9q2RYJObm7EdHUhHHIjS2Wsm15EFxVg+i/I3oQKdUwX8Z94dRq8dOV3cK0nt8088omtMHDKDRsfroE21y2x0wyiOIySruVIkBIcakdhKUGw2tCv12X1nKBKmQnxRYOM5P28+Gdiq9CGS8Aw2Yngs3NsqMINJsRzY0pWik6IaS41A7CUjfh6V/hK5UlforZyVAVb5ip92wTefA0fOokcFCw2Ylgc7PwI1bVLEYibkxPSlELIUVIVg2iEpJKl5EK1D25deoBLug6dlKsZn8Rk7bTs2OTyO04oDfVuDch2OxEsLnZ6/UZeloJUdyYnpSiRkJKDqJjknrUaCzop2t+f+F+TZ9jJ7nFcefjDZQLXyuAH+g6fRxut9stwWYngk3NMlh5T0xCFDemJ6WoWkgRogdRCUl9bLd3+D2hIoCdhG9Qy4AiKAQiSYYkLdgGMcUO0kUvIu0+iJKTUvTGmzbZpg5Xca2mI/fIHwUXNRn9pRNsQkwF4CBd9AAhJTQolFJxJ1x9BIscOvuck3VKOrGT9V31epbq5GR5PHwpdlnNXbAk1ImdrOyq17NU6GRGfziTXf4rJHWs8hsrh+HGgvAwxAAAAABJRU5ErkJggg==\n", "text/latex": [ "$$\\left [ x + y - z, \\quad 2 x + y + z + 2, \\quad x - y - z + 2\\right ]$$" ], "text/plain": [ "[x + y - z, 2⋅x + y + z + 2, x - y - z + 2]" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "equations" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "A = sympy.Matrix([[1, 1, -1],\n", " [2, 1, 1],\n", " [1, -1, -1]])\n", "b = sympy.Matrix([[0, -2, -2]]).T" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAC0AAABMCAMAAADObM5XAAAAOVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACXHtMAAAAEnRSTlMAMquJZkQiEEAwzd12VJm773wARP+8AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABWElEQVRIDe2X25KDIAyGw6GwK/Gwef+HXUCJ0CmTMtvZ9sJcaITPXxIOAoBgU1OvKJtuCs8HpOSHHQJQZGy02wnU3m3OdCKsjq4iV1e3vkef6VxqJRphgJ7dAO0sDNDKGLOQmY9YxHYDOPIlcJm2K+kB7SIc77J2Bbe0n8JpqsYOX9DeB0e87rhA3+m/lnZoUXMIkrY2ALiVBkm0irqGJ49EJ9UQh9ZuMo0TFrjtHS5tHL8yLmunmViSItB+i6Cj0nCBhhDHtt3KAJdoZRA1LwkS3cT7TE6qF16lrVKAd9bR9nqZzqnO73ToWI8XzVkqTi8nX/RdkOr+iP7p/kke0e/oHb1uFDRP3yOefkuqgNm9aE4FO2JOvOXVW/5fKsTA0k+sPvNFn+k6vJGcODPRwpNC7MvmW3+gP3rvc+1mmm7mh//czfRPR7yb4dORzyef3unoaP7OWPgF3fQZJY/ujMUAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left[\\begin{matrix}- \\frac{4}{3}\\\\1\\\\- \\frac{1}{3}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-4/3⎤\n", "⎢ ⎥\n", "⎢ 1 ⎥\n", "⎢ ⎥\n", "⎣-1/3⎦" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "A.solve(b)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 2.49 ms, sys: 882 µs, total: 3.37 ms\n", "Wall time: 10 ms\n" ] }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAC0AAABMCAMAAADObM5XAAAAOVBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACXHtMAAAAEnRSTlMAMquJZkQiEEAwzd12VJm773wARP+8AAAACXBIWXMAAA7EAAAOxAGVKw4bAAABWElEQVRIDe2X25KDIAyGw6GwK/Gwef+HXUCJ0CmTMtvZ9sJcaITPXxIOAoBgU1OvKJtuCs8HpOSHHQJQZGy02wnU3m3OdCKsjq4iV1e3vkef6VxqJRphgJ7dAO0sDNDKGLOQmY9YxHYDOPIlcJm2K+kB7SIc77J2Bbe0n8JpqsYOX9DeB0e87rhA3+m/lnZoUXMIkrY2ALiVBkm0irqGJ49EJ9UQh9ZuMo0TFrjtHS5tHL8yLmunmViSItB+i6Cj0nCBhhDHtt3KAJdoZRA1LwkS3cT7TE6qF16lrVKAd9bR9nqZzqnO73ToWI8XzVkqTi8nX/RdkOr+iP7p/kke0e/oHb1uFDRP3yOefkuqgNm9aE4FO2JOvOXVW/5fKsTA0k+sPvNFn+k6vJGcODPRwpNC7MvmW3+gP3rvc+1mmm7mh//czfRPR7yb4dORzyef3unoaP7OWPgF3fQZJY/ujMUAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left[\\begin{matrix}- \\frac{4}{3}\\\\1\\\\- \\frac{1}{3}\\end{matrix}\\right]$$" ], "text/plain": [ "⎡-4/3⎤\n", "⎢ ⎥\n", "⎢ 1 ⎥\n", "⎢ ⎥\n", "⎣-1/3⎦" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", "A.solve(b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can repeat the solution using `numpy`. This is considerably faster than using `sympy` for large matrices." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "import numpy" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "A = numpy.matrix([[1, 1, -1],\n", " [2, 1, 1],\n", " [1, -1, -1]])\n", "b = numpy.matrix([[0, -2, -2]]).T" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "matrix([[-1.33333333],\n", " [ 1. ],\n", " [-0.33333333]])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "numpy.linalg.solve(A, b)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 113 µs, sys: 24 µs, total: 137 µs\n", "Wall time: 129 µs\n" ] }, { "data": { "text/plain": [ "matrix([[-1.33333333],\n", " [ 1. ],\n", " [-0.33333333]])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", "numpy.linalg.solve(A, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The numpy version is much faster, even for these small matrices. Let's try that again for a bigger matrix:" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "N = 30\n", "bigA = numpy.random.random((N, N))" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "bigb = numpy.random.random((N,))" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "40.6 µs ± 1.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)\n" ] } ], "source": [ "%%timeit\n", "numpy.linalg.solve(bigA, bigb)" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "bigsymbolicA = sympy.Matrix(bigA)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [], "source": [ "bigsimbolicb = sympy.Matrix(bigb)" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1.18 s ± 69 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" ] } ], "source": [ "%%timeit\n", "bigsymbolicA.solve(bigsimbolicb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Wow! That takes about a million times longer." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Nonlinear equations\n", "\n", "In some cases, sympy can solve nonlinear equations exactly:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [], "source": [ "x, y = sympy.symbols('x, y')" ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAANgAAAAVBAMAAADWeD20AAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQiVBDNmWbvu6spOvyJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACcklEQVRIDX1VPYgTQRh9idncXHLBcBZCCg2nqJUE7b2ol1IRGxGE287iEBaxsMtYWojhGosDPUEQsYl2iuKBHtid14iNYmEhgnCF4k8Tv+/bzO7szKwfJPu+9715b3d2s8H8AaCO0iobxaUrggO2oaQBHfYGBUJG7eCskgTpUlJsBhw20weWOrGvPKbLTuSaJe5YOAiNjYTdBGYTdcgVqm/3NE3o45UaWdRBCwdgbiNhj4GnwBlfuF8DzXWfR2McIEspYyNhG8AnYKg9Navw1qOBuQBXThkbDotoT/4Cy/49F9VawOVigCunjA2HNfpQHOZvjajOBlwe5JzqtFHZmkwm6znnIGPDYbNj1H8Ai21HA4jqmUcDazlXizawdOH0k+M55SJjw2HVJA3ru6I07KpHA4dz7nJjtCupxHtyxkMSRjYcNncOiq5sueTKFr3FwCagVhe4eno3rWvhq6cygukGkc00jB+QYeLp5ZQuebSEZexQAyfQzXofGBu5Z5TyEXhFi5wSVWgb71jCu4QfYsdiXGhsOKxF+/ACeAQVVL1kVhdH23mrftWgfuOnL8o0EkY2HFb7DHpI1GvcHmXzFIjqPmH1pzixfg7RzgoqI7zxRdkSY8NhUZeEJ/f1UD2SzQV83zpKFy3vzAVdGJ23uu0xWgm+EOOIjCaz4TDQP1pa1w2wjvUuNzOav7Oq9jJoAUdkTegvs5tuI54bum+AdUzfuTWLIRh8O8MRFZawjVxZK055RZvm1RVhbjj8e6cPimwN20iYepfSTXtq8AcBdF6FulXopo0rsjVsM8ApumMrNl3EzbjYT7v6/4wDK9hmfvMf/WqBXLmg8OIAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left [ \\left ( 0, \\quad 1\\right ), \\quad \\left ( - i \\pi, \\quad -1\\right )\\right ]$$" ], "text/plain": [ "[(0, 1), (-ⅈ⋅π, -1)]" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.solve([x + sympy.log(y), y**2 - 1], [x, y])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can also specify the kinds of solutions we are interested in by increasing our specifications on the symbols. The answer above contained a complex answer. In engineering we often want only real solutions" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [], "source": [ "x, y = sympy.symbols('x, y', real=True)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEoAAAAVBAMAAAATJmVgAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQiVBDNmWbvu6spOvyJAAAACXBIWXMAAA7EAAAOxAGVKw4bAAABMUlEQVQoFX3SMUvDUBDA8T/BxJfGgrgIDloQxEnEL9Aodqz4AYRmFyE4ubWrk90d1FFcgpuiKIjgpqOL4iy4OTl5eZdIkzQehJfc/bi7kDCzCB61kZaEdOSYrUW401LrpGoyhM25qErXBtrBqkPwY7NUVubzRJQvl1UXcAndsoIFEcFppu7hHfqSKkWqeFLlDuEHenHJaC+OVTVCTKqS8WpLlZ/gfUM7fedi2IlXqpxYVVgk8mTVvqqpbYz06tX0av+pdPt+zfY72V5SfoO7wb8TmzLqBs4xZWb3utVeEx/gxOaBo2GJWXWmym2BWZ9fxVkuqq/nFRkj39d+R/nDNA7ym5HTa2XqOk+G+c3I2Ugy1Yw0a6R/JfYkYyeaF60FFSKJV6s2ZKvdcWXNBZH894+/wXY/0n4lWaAAAAAASUVORK5CYII=\n", "text/latex": [ "$$\\left [ \\left ( 0, \\quad 1\\right )\\right ]$$" ], "text/plain": [ "[(0, 1)]" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.solve([x + sympy.log(y), y**2 - 1], [x, y])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "But sometimes nonlinear equations don't admit a closed-form solution:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "unsolvable = x + sympy.cos(x) + sympy.log(x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`sympy.solve(unsolvable, x)`\n", "\n", "```\n", "---------------------------------------------------------------------------\n", "NotImplementedError Traceback (most recent call last)\n", " in ()\n", " 1 unsolvable = x + sympy.cos(x) + sympy.log(x)\n", "----> 2 sympy.solve(unsolvable, x)\n", "\n", "~/anaconda3/lib/python3.6/site-packages/sympy/solvers/solvers.py in solve(f, *symbols, **flags)\n", " 1063 ###########################################################################\n", " 1064 if bare_f:\n", "-> 1065 solution = _solve(f[0], *symbols, **flags)\n", " 1066 else:\n", " 1067 solution = _solve_system(f, symbols, **flags)\n", "\n", "~/anaconda3/lib/python3.6/site-packages/sympy/solvers/solvers.py in _solve(f, *symbols, **flags)\n", " 1632 \n", " 1633 if result is False:\n", "-> 1634 raise NotImplementedError('\\n'.join([msg, not_impl_msg % f]))\n", " 1635 \n", " 1636 if flags.get('simplify', True):\n", "\n", "NotImplementedError: multiple generators [x, cos(x), log(x)]\n", "No algorithms are implemented to solve equation x + log(x) + cos(x)\n", "```" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Numeric root finding" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In such cases we need to use approximate (numeric) solutions. When finding roots numerically it is a good idea to produce a plot if possible:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.plot(unsolvable)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We see the root is between 0 and 1 and there appears to be an asymptote at 0. Let's zoom in a bit" ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.plot(unsolvable, (x, 0.1, 1))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sympy.nsolve will attempt to find a root starting near a starting point. 0.3 looks like a good first guess." ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAKoAAAAPBAMAAACGiUnsAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAiXaZIs1UEN1mu6tEMu+iw/3TAAAACXBIWXMAAA7EAAAOxAGVKw4bAAACz0lEQVQ4EW2Uz2sTQRzFX5rtbpJN0qUqgiCNraAnDaxVpJUu1oM/DsnBX9hD27/ALSh4spFCLfbQ0CriLYhSL2KkoNYgycWTByN6UDzYg6hYsLU2Vmvb9c1Mkq4/Bnb37ff73meGnUmAf4Z2XZTKMJy/W//txIBzfqMKBpr3yGJ3+11gYFsndM/z1jB3YsQFXvMymjeUoNlnyn908FKkYknEK6cvK6XsKngSFxxWtTxaSkjC7Av02PYwRn5shjHVS2oQeIBjCKxgvcPAKC+E8giNXaJJKGUXQYQzCORYNV3EZ8JZGGlStCTyrAG7GbgBnMdD4Ivg1zsNkrozD1MaQaXsMhjJQ19iIb4Ec5F8I61zCvioWwR1zkXR8Xfe9DAUu1ajCuWjNiUR/c6CmYG5Gl12g1m+bPVTn09iPx4BxbK/YwlqoLFGFcpHHST1JwscoXkUF/ZSaDlguvUAlfgCptfWR4kxXvVOgyOo2wV1vI3TCaXsMpiyEFtggeNdAgHvOIVZAiaR4l1Q0VJxeJeueucISNWyZEVcbUUpZZdBQf3KEMcQ0H/UKwEp+RrJKJu+8d4KC6Ekb/WOJagByBXiTk3JRYDBQQtRtdZgEuEkzn4ENklqcFFRJ6Cvccm2KNY6YUdQr1apXU5VKSqD3C1d7BYwwYPgQuPLFSCSRnBVUTlNqk9MyFHrHASpWkJQbwNdr6SSdhWM5BAWJwu6hUODfE7D+EU+j8S8tBl8mFn0Q3PWO88KhbX70UKhOGt94ulQStpVMDyDYFpQXwA74g5wC9Fv4pMhnlNrfc+VOzELDa6/g1kRiudhAZ+VkvZqcBgXy0YF2pDdkYmeQjgBnbvH39AuV1GfuhjHYdvmkfV1sCyoTTl0o4HfSChprwYHWp+I7W/kf0oab+1OEj/Q0N2xD3g8N5pAbMouodfzKv4O2r2b/IvoXU5o9hSnF0rZRfA3q8b5GoZozSYAAAAASUVORK5CYII=\n", "text/latex": [ "$$0.287518275445415$$" ], "text/plain": [ "0.287518275445415" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.nsolve(unsolvable, x, 0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If we're going to be using numeric methods anyway, we can also use the routines in scipy.optimize to solve equations:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [], "source": [ "import scipy.optimize" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The function `sympy.lambdify` can be used to build a function which evaluates `sympy` expressions numerically:" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "plus_two = lambda x: x+2" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAOBAMAAADkjZCYAAAAKlBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADmU0mKAAAADXRSTlMAMpndq3ZmzYkiRO+7EDr+BQAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAD9JREFUCB1jYGBgEAJiBgYTEMEKJsVKQOwGEMk6AUROYwCRDSCSbQKInMoAIpe4uNz2AEowbAERDHdAhPrdowCHcQzAI1BqtQAAAABJRU5ErkJggg==\n", "text/latex": [ "$$4$$" ], "text/plain": [ "4" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "plus_two(2)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "def plus_two(x):\n", " return x + 2" ] }, { "cell_type": "code", "execution_count": 35, "metadata": {}, "outputs": [], "source": [ "unsolvable_numeric = sympy.lambdify(x, unsolvable)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMoAAAAPBAMAAABXbk2cAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAiXaZIs1UEN1mu6tEMu+iw/3TAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADUUlEQVQ4EXWUT4xTVRTGf512+uZ1Op12CJCYGApsSEicxooSBqSRjbBwmviHgBGehjV9hA2raYOgJLDowoVspKiJ/xaMYaEwKG+HiQnzgAUSInZBmIWaGdApDJmxnnvODIQEXtLvnPd9597vnXveKzxxxXiVJ4hn3WwPn6U8nU8MvaSCxum3j8ny3+SXKmyKIFF4fjGjUIg5sHqzq70GtW6326Y8IpXJ8g/COdlASYXC2sqS8g6HXI7GYw9W4p3dK2sP4ndIneBHy3g96m9Qoj+Q0uOw/Gx5Y3CoOHAb7zC3KiZrjZIKvYF3BFP8BomWrLQ4LhkMi8tw4M3SW+Jby3iTTMtv4lWhR1xKsI2f4Qv622RKKhsoqfApPIeRmXHS92Vni49dLkfMUhM7NNMaeRzncuNdCGBcCljFYJXEjMoKRqrynRxsaORgiWxH9rL42AXSc+wRQS7JetsSsw/DZBPy4iIji72H0nJcb9GzoLKCktdV+QcmAyWpi8ucLLJ4bs0Wyd2JwS9NZq+sjSwbfG9IBn/x3styYBV12YE+duR6mVfZalwbkYNLzqVp5GiegXuyk8WvGJVt1eXqROzNNrkDklHfRS4g0X0LtqMuF3BzOdN0c5lT2WqUdPDJXfijaKTbXW7VxcVMY6mXdMfrwqvSV7pDfYbkFO/v6Ebk1SU1A2PRwMXA+4ubHZWtRkkH+5xL3sh6nqzrZSkm/11yYTp8AKciEafDwQb+vF+iNuVX1CVRBe/FFcMxB1d/sKCygpFOuS4uk0UjZeryqDr9dCdTJblgLr9Lz8FRcWlq1lfFn8uFpDqvoS59LVkEW90Ik/dVVnhEbg1lLrXAyEwLX99kF3MN+uUkZC5eNxSXr8XlkmZykP58XbY49+vExH/fS+/jbj92O+htqazg7pXcLZ8ap0Ij/TZJaR6NCci1rJc/3TlNylzQLCtzaecq8KXUCsNkCfaHqQXSU4zGKisYqcpnsAEj+YgxeZnQmCrxQmguJ91Xksl7d9CM04wF2Z34RXGQr4FaHtaFmSY9H/MNKhsoqdAXeH8vKhxY8xN8iMVtI6/A+enjRbLlTREsG4kXs0RZym6W5aNhQ/dzeCNw/6XutrBMClU2cKQq3tD62JT/AQYUYMNA9qUeAAAAAElFTkSuQmCC\n", "text/latex": [ "$$0.051363684799669906$$" ], "text/plain": [ "0.051363684799669906" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "unsolvable_numeric(0.3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the kind of thing we can pass to `scipy.optimize.fsolve`" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.28751828])" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "scipy.optimize.fsolve(unsolvable_numeric, 0.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`fsolve` works for multiple equations as well, just return a list:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [], "source": [ "def multiple_equations(unknowns):\n", " x, y = unknowns\n", " return [x + y - 1,\n", " x - y]" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAEoAAAAVBAMAAAATJmVgAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQimc27qxDvZlRT12JPAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAxklEQVQoFWMQUmYgBIBKXAmpAcq7AiFbeacBbqVGGyCqshhYvuJSxb28H6pqNQPDGVyqGBjkoarOb2BYn4BTGUzVIgaG9bgdBlMFNEYfp1FwGxkYmD8So4qpgBhV5RiKuJuUQADoXLi7ePEYhVD1hIEtAcM0mADMLGYHBsYN3DBRdBqmKqm8fBHD/gZ0aSgfpqr///8fDEza2FWtPK8lAE4TEOnX2FWBRUEpBwIcoDQ2Cq6KWwCbNFQMrooXjyKgfU5EpPujAGpHL91T5t6cAAAAAElFTkSuQmCC\n", "text/latex": [ "$$\\left [ 2, \\quad -1\\right ]$$" ], "text/plain": [ "[2, -1]" ] }, "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ "multiple_equations([1, 2])" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "array([0.5, 0.5])" ] }, "execution_count": 40, "metadata": {}, "output_type": "execute_result" } ], "source": [ "first_guess = [1, 1]\n", "scipy.optimize.fsolve(multiple_equations, first_guess)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Downsides of numerical solution\n", "\n", "Remember the downsides of numerical solution:\n", "\n", "1. Approximate rather than exact\n", "2. Requires an initial guess\n", "3. Slower to solve the equation every time rather than solving it once and then substituting values.\n", "4. Typically only finds one solution, even if there are many." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Differential equations\n", "\n", "Now for differential equations.\n", "\n", "We'll solve the \"classic\" tank problem:\n", "\n", "![Tank system](../../assets/tanksystem.png)\n", "\n", "\\begin{align}\n", "F_{out} &= kh\\\\\n", "\\frac{\\mathrm{d}h}{\\mathrm{d}t} &= \\frac{1}{A}\\left(F_{in} - F_{out}\\right)\\\\\n", "\\end{align}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Analytic solution\n", "Sympy can solve some differential equations analytically:" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "h = sympy.Function('h') # This is how to specify an unknown function in sympy\n", "t = sympy.Symbol('t', positive=True)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "Fin = 2\n", "K = 1\n", "A = 1" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAACAAAAAVBAMAAADV4/HZAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAELvv3c2ZVESJZnYiqzKqLvLVAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAA8klEQVQYGTWNL0tDURiHn7Pt3t1dNlzQ7IbNpNF2qyBiMphWLFoWTGMwwQ+wGzQYhCFosHixWA+LFseqCH4DRbAOf++52wu/P+fhvOfAcpqWwZbg1TIpwG1lVuu5OYajnrUNad0TtWGtb+BMGkHag7Eg7Ein0i5c2zk5ku1LJ3A8ePHEOcn89wPucH++NSOa6KMf3XigvqDVodaH2NYuLKoF1Uuo5QLfFu9fAWwKcoVC/0RaGeNs5Rn20nalgBuGcM8cFg0aM/h0oudsw21BksH0SW8cSGEOy2hmZcJjWeLJClR8aNPVGdcJtRs82Jt56vkHx+kxKzDmnxIAAAAASUVORK5CYII=\n", "text/latex": [ "$$h{\\left (t \\right )}$$" ], "text/plain": [ "h(t)" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "Fout = K*h(t)\n", "Fout" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We use `.diff()` to take the derivative of a function." ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAMQAAAArBAMAAADVmjoPAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMt0Qq5nNdrvviSJUZkQZkPbxAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADdklEQVRYCbWWTWgTQRTH/80mMd/NyYMeEqO9qIdFilIviSCkxyBaQRGDUERQiKgo4iFiEXsorYjgB8IqYqUXc7BQEOnixUORhoKiB2kPXnoobS1WqfXjvZ1Jk6azaQeaR3fm7bzff15mZ/ZtAV1rOZfTlWjzrba2RFcwa+oqtPln2gptQbe2Qk8QPnFxWU+hTU+XAgvaIi2B8QS+vJZCG/YtwGNpq7QEwSLSU1oKbThtYVJbpCdI27gdKelp1HSYh52mLu4vRNtCtWOuZC2k8m/wYKywNmRkn76+WDvsStZCLTvF3dCVEozeJN9ELG7hyB1vbbMOOdx109GEBk8C7V3iVfLbxh7A7xTq/RTeV4K/Ub1rSIYzeDXFOc7zPNgiUkwALwFRqE9RcByIOvnIn2G6ztSkhLwmggPkR5MIFVdS9NCsJkSh5mgXXffoYnsvulWtmpRIcAHe3+QHMojQCuQqfgCzNpxCHctTdDddF+hiU6VQk4KHNwnvPPmtOcSoaooUBqcoo/vDtRJ8FmKdv7LAc6lQpVCTUkCdZ46aNKX4U0kRXgISBWOx5M3AX6ZDxcQnqVCkcCGlgLpEgZpRCy0/V6WwIvPwFuGxIerpO6LYFClcSMFz28YNp6DfLh8UebMFKtTBAoJTtE6LiARdOJJKPUyldrFbYyrSOJNiizPmy3Gbpke+sgrQXozbNPFo3Enh1NNpxsgqq2j9VzH+CSpS8NR+dDza7sjKduMOMGnSxHRS/DatCAbQ4EG5kM7E1EQsvKEuUES0emi/8KtAhfpR1AzQTr3AGPBZKiqrqExAvQtZIbYBl8iPDjibynuRztMeG3fRCcyHEMoAhw3Kc1wqFClcSCkItx07mjQWgb3oiMPb+z0LTw7G4OU4+oChAmJJYOQr0VS0HFOkcCGlwE97ludDdfDqITlU1+0Q9+GkHFekkJF6Ug6v34njAF9ZojM1kq33a27kwamStbGGfqDkhEeU0DK46ktrSFYgVW8UndFbqlhsQRQXEWtEqtTVsbfsRsVaqqOOF0qu+metAVkn3Pgtfe081sZxfXJ4MGF/6++hd6ZZFnuMfpO/uc2zjjJ/cPmb2zQ7bfIHl7+5TbMHMP7yX/PMWEJ0DrE5mE3LYSwjkB8L5SPKN2Zz0p7FRM7yZg5szmzKWdqvb8/Gw31lZdBt8D9u8frhiMp2ugAAAABJRU5ErkJggg==\n", "text/latex": [ "$$1.0 h{\\left (t \\right )} + \\frac{d}{d t} h{\\left (t \\right )} - 2.0$$" ], "text/plain": [ " d \n", "1.0⋅h(t) + ──(h(t)) - 2.0\n", " dt " ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "de = h(t).diff(t) - 1/A*(Fin - Fout)\n", "de" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we calculate the general solution. Notice this equation just satisfies the original differential equation when we plug it in, we don't have specific values at points in time until we specify boundary conditions." ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAL4AAAAYBAMAAAC2H1pdAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAELvv3c2ZVESJZnYiqzKqLvLVAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAC+0lEQVRIDZ1US2gTURQ9kzSZTJx88Ad1YaPuBLXiShAdQSqCtgFBUVykYF20FbtwoxYMii66aYR2UYI0CHXhQqd1oRCEoQsXIiR04UKpBBeCqzZCLf3Yeu97M8l0TNKQC++9e88592Tem5cBWox9SW7UshngRosWjdqieYPpLB5BWWwkbJVTDe48jZilip1s56OzQEzbKSUv/PV1+IfHrpWaaHnHmpDZhFJKhH+0jLZcYKhRk3LIYFrNCJH4FZFVJ2Vm/qsu6SoIx99vxuIumNOPfUcFomUHaQ2kuNhDY7eFgFdL8NtpqGM5SmT8OEhhSX86n9jQY4exV72IyTTnV9mRBJz303gIhFNcbImdZ6m8Y23BqKi+3w+KTY5ITSQOfyelYQNaAhgVj8xAH43jNLbGZea9zyj8lQzdzycY0OyGB3L1lxFZp9RXhFoGxhgNJWm6QOM6V+7Qlrn66YY418f/mNFT9P/qxdPXNmn7RwxENgiKpRCi5iv3ZywEMwjN/f4GPLe1laVgcLpf1u35XpnUnG1/4toWaeog/1UoS1akiECOdszgFA3g5jmOS5xOmjzLCHXjl5PXWKv+C9xUyCC6BnUDkQTahoBgksC73r6ekkT4e1PI4b2Xd9VV/y5G2X+FXf0m/GnaVIbABWbccSbOVVx8b47lJ9Juzp3Tlk/YW0YwxUwHnfkauxZKwr8jTeB/F6WHpWpJ3Me/nNePyvO/FBp6v+oyyJVuEP/HR6E450MPQyHOX9x8uoF831fqezPj+NO34DOVvgTCZbwBTobjPhMYxzDwwmtRIAbPpD9dYNXLu2rHn+7ANMHhTj78OWBDg1YE5hWyGnDpRaquAvfi0n8KyqCXd9W2v95167ahLAHnsauEw8CEiZABzL4i7UWXXqZ7j3xJU8bnsyObl1jt2fYPbG5uJkFXqD3/vSLslpluVBBPwv7bhHM+tWTylSOYq0Uy1oT/SL1ewn2WIGfrSfh7U49rBlcSQnWgGW1Lmk/cFbZa6m3Q9A8Ndakyiw5skAAAAABJRU5ErkJggg==\n", "text/latex": [ "$$h{\\left (t \\right )} = C_{1} e^{- 1.0 t} + 2.0$$" ], "text/plain": [ " -1.0⋅t \n", "h(t) = C₁⋅ℯ + 2.0" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "solution = sympy.dsolve(de)\n", "solution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need a name for the constant of integration which Sympy created. Expressions are arranged as trees with the arguments as elements. We can navigate this tree to get the C1 element:" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [], "source": [ "C1 = solution.rhs.args[1].args[0]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can find the value of the constant by using an initial value:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [], "source": [ "h0 = 1" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAADEAAAAVBAMAAAAdjxsPAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAdt0yiUQQzauZu+8iVGYiSztUAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAApklEQVQoFWMQUmbAAhiVDBhcsYgDhVgCkGWY1SCqXCQPoMpkTP8GlmG/wKaDKsPACJF5xMDghV1mBQPD/QRUe6B6fjIwxF/AJsMGknmATYbnCwODvQBOGQewTLoSCACDAmIPG1BPPFY9DEB77mN1AcMqBob32F39moFhOgOmC/ILGJgusG1GleFY/amRgWkCA5ujhAGqDEp0oJqGLEWmjBP2dKAdAADtSzRe1nXKQgAAAABJRU5ErkJggg==\n", "text/latex": [ "$$\\left [ -1.0\\right ]$$" ], "text/plain": [ "[-1.0]" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "constants = sympy.solve(solution.rhs.subs({t: 0}) - h0, C1)\n", "constants" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's see what that looks like" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "sympy.plot(solution.rhs.subs({C1: constants[0]}), (t, 0, 10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Numeric solution" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When the boundary conditions of differential equations are specified at $t=0$, this is known as an [Initial Value Problem](https://en.wikipedia.org/wiki/Initial_value_problem) or IVP. We can solve such problems numerically using `scipy.integrate.solve_ivp`." ] }, { "cell_type": "code", "execution_count": 51, "metadata": {}, "outputs": [], "source": [ "import scipy.integrate" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [], "source": [ "Fin = 2" ] }, { "cell_type": "code", "execution_count": 53, "metadata": {}, "outputs": [], "source": [ "def dhdt(t, h):\n", " \"\"\"Function returning derivative of h - note it takes t and h as arguments\"\"\"\n", " Fout = K*h\n", " return 1/A*(Fin - Fout)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`solve_ivp` will automatically determine the time steps to use, integrating between the two points in `tspan`:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [], "source": [ "tspan = (0, 10)" ] }, { "cell_type": "code", "execution_count": 55, "metadata": {}, "outputs": [], "source": [ "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We'll need a smooth set of time points to evaluate the analytic solution" ] }, { "cell_type": "code", "execution_count": 56, "metadata": {}, "outputs": [], "source": [ "tsmooth = numpy.linspace(0, 10, 1000)\n", "hanalytic = 2 - numpy.exp(-tsmooth)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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s10IXzf95u4EWs11tgVazUy/uftln7NPnz58/fXXvPTSS3z//feEhISwf/9+OnXqREJCAgAPPfQQa9eurfO8iIgIOnfuzMaNGykqKmL//v0kJyezevVq0tLSGDRoEImJiaxevZpDhw41Wkf//v3Jz88nNzeX7du307ZtW2JjYwEYPHgwnTt3xmw2c99997Fu3bo6z23Tpg0BAQE8+uijLFu2jKAg18pmGzZs4P777wfgwQcfvOB5l6uh806YMAGTyUTPnj05ceKEW67nkS30yNBAjpWU08OUQ6W2cFh3qNkuhKDmL1V3jnJJSEggLTTiFrIAAAz7SURBVC2NL774gpkzZzJmzJgm9xXfe++9fPLJJ/To0YM777wTpRRaax566CFeffXVS65l4sSJLF26lOPHjzNp0qSa7eeP3T7/scViYfPmzaxevZrFixczb948vvnmmwvOX98YcIvFUtOFc7nTL9Q+r7//j9N8a60v63zn88gW+rnWR1d1lEO6I3YsV9z6EMLbTOgfReqMUWTNuZXUGaOuuDsyNzeXoKAgfvazn/HCCy+wdetWevToweHDh8nIyADgo48+4oYbbrjguXfddRcpKSksWrSIe++9F4DRo0ezdOlS8vPzAVd3yJEjR5pUy6RJk1i8eDFLly6t01WxefNmsrKycDqdLFmyhOHDh9d53pkzZzh16hTjxo3j7bffJj09HYCkpCQWL14MwMKFCy94Hrj68NPS0gDq9HkHBwdTWlpab51NOa87eWQL/dwPZreUY+x0diZKxtgK0ex27tzJ9OnTMZlMWK1W5s+fT0BAAB9++CF33303drudQYMG8cQTT1zw3LZt29KzZ0/27NnD4MGDAejZsyevvPIKY8aMwel0YrVaeeedd4iLa3wIcq9evSgtLSUqKoqOHTvWbB82bBgzZsxg586dNW+Q1lZaWsodd9xBRUUFWmveeustAP70pz/x8MMPM3fuXCIiIvjwww8vuOYLL7zAPffcw0cffcSoUaNqtt94443MmTOHxMREZs6cWec5TTmvOyl3NfUv1cCBA/WVjFGtLD+DdU40G2MfJemRhseJCuEN9u7dy7XXXmt0GS3WmjVreP3111mxYoXRpbhNfd9zpVSa1npgfcd7ZJcLQF7mbkxKY+3Qw+hShBCiRfDILheA4iM7iAfaxfUxuhQhhBsNGTLkgrHsH330EX36NPy7PnLkSEaOHNmMlbV8HhvoVcf34dCKqC4S6EJ4k02bNhldgsfy2C4Xv5MHyTN1ICAwyOhShBCiRfDYQG9XlkVBQLzRZQghRIvhkYFut1UR6ThGRWhXo0sRQogWwyMDPe/wPvyUA3N7GeEixNX26aefopRi3759V3SeKVOmNDop1R/+8Ic6j5OSkq7omhezZs0abrvttgaPKSkpqTMpWG5urlvmX3Enjwz0osM7AAiJbblTfQrhrRYtWsTw4cNrPgHZnM4P9PXr1zf7NS/m/ECPjIx02yyJ7uKRo1wqcl3LznXs2s/gSoQwyJcz4PhO956zQx+4peGFGc6cOUNqairffvst48ePZ9asWYCrhTtr1izCw8PZtWsXAwYM4OOPP0YpxezZs/n3v/9NeXk5SUlJ/PnPf64zp8nq1auZN28en376KQBfffUV8+fPJyEhgfLychITE+nVqxcLFy6kdevWnDlzBoDXXnuNjz76CJPJxC233HLBohL//Oc/+e1vf4vZbCYkJIS1a9dSUVHBk08+yZYtW7BYLLz55pvceOONdZ43a9YsWrduXTO1bu/evVmxYgUzZswgMzOTxMREbrrpJp5++mluu+02du3addHzLliwgOXLl1NWVkZmZiZ33nlnzayTzcEjA91cfJAThHFNSDujSxHCp6SkpDB27FgSEhJo164dW7du5brrrgNg27Zt7N69m8jISJKTk0lNTWX48OFMmzaNl19+GXDNOLhixQpuv/32mnOOGjWKp59+moKCgpqPx0+dOpXbb7+defPm1cy3UtuXX35JSkoKmzZtIigoiOLi4guOmT17NqtWrSIqKqpmmtx33nkHcE1jsG/fPsaMGcOBAwea9NrnzJnDrl27auo5fPhwzb6Gzpuens62bdvw9/ene/fuPPPMM8TExDTpmpfKIwM99GwW+f5xXGN0IUIYpZGWdHNZtGhRzVznkyZNYtGiRTWBPnjwYKKjowFITEzk8OHDDB8+nG+//ZbXXnuNsrIyiouL6dWrV51AV0rx4IMP8vHHHzN16lQ2bNjA3//+9wbr+Prrr5k6dWrN9Lft2l3YuEtOTmbKlCncc8893HXXXQCsW7euZnGNHj16EBcX1+RAb0hD5x09ejQhISGAa/6aI0eOGBfoSqkPgNuAfK1173r2K+CPwDigDJiitd7q7kLBtVLR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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(sol.t, sol.y.T, 'o-', label='solve_ivp solution')\n", "plt.plot(tsmooth, hanalytic, label='Analytic solution')\n", "plt.legend()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that `solve_ivp` is taking really large steps but is still getting a really accurate solution. Of course, because we are taking such big steps to solve the differential equation, we now have a problem of interpolating between those points. The linear interpolation is clearly not very good, so `solve_ivp` supplies an extra argument which allows us to specify points we want the solution at. Note that this does not change the step size. The same steps are used internally and are then interpolated using a smooth function which is known to approximate the solution to the differential equation well." ] }, { "cell_type": "code", "execution_count": 58, "metadata": {}, "outputs": [], "source": [ "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0], t_eval=tsmooth)" ] }, { "cell_type": "code", "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXQAAAD4CAYAAAD8Zh1EAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAfT0lEQVR4nO3deXiV9Z338ff35JzsISwJS4CwKIssyhIBq1I6tYjLVPuordpqdZyh81x20VnstM+0tuNMbceZTrXVInXBtg6dqbXqqI+4S1sRAQXZF1lDgISd7Gf5zh9JLXsCnOTOOefzuq5cSc7vzn1/ThI+/HKfezF3R0REUl8o6AAiIpIcKnQRkTShQhcRSRMqdBGRNKFCFxFJE+GgNlxSUuKDBw8OavMiIilpyZIlu9299HhjgRX64MGDWbx4cVCbFxFJSWa25URj2uUiIpImVOgiImlChS4ikiZU6CIiaUKFLiKSJtosdDMbaGZvmNlqM1tpZl87zjJmZg+Y2QYz+8DMJnRMXBEROZH2HLYYA/7W3d8zsyJgiZm94u6rDlvmMmBY69tk4Ket70VEpJO0WejuvgPY0frxITNbDfQHDi/0q4Cfe8u1eN8xs+5m1q/1a0WkHTwRJx6LEU/E8HiMeDxOPLsIT0CiYR+Jxlo8ESORiOOJOImE01Q8lIQ7Wfs3Qv2+lsfjsZZ1hbKp7T0Bdye3ZjlZDXtxT+AkIAHRcD77e08i4U7xroVkNe4Dd9wT4E5TdndqSqeQcOhd9Trh5gMt4zjuTkNOKVUlF5JwZ9D2F4hEa3F3nATucDC3jK29LsIdzqn6DVmJZjjsct37C4ZQ2fMCAMZUzsU8DoddzXt30XCqekzCEjHOrfzPI79XDtXdxrCj+wTC8QbGbP+vY76fO4rHs6v4PCLRg4yp+vUx49t6TKGm2yjymvcyasdvW6P9KcDmXlPZUzicwsadjNz5HAB22NdvKL2EfQVDKW7YxvCdLxyz/jW9L+dA3kB61G1kWM3LHz1em9Ob3Cm3ceHZJSf7dTgtp3RikZkNBsYDC48a6g9sO+zzytbHjih0M5sJzAQoLy8/taQiHchjTTQc3EN93SHq62qJNtbR3FjHnqJzqCOXyJ61FFUvJtFcj0cboPXt1dKb2JcoZPi+t5hw8DVCiSghj5KViJLlUb5T+G0OeR6fbvgtVza/RNhjhIkRJkrEY0yO/Ywmz+Jboce5JfwyYf70j7LJw4xu+jkA/x75Kddk/e6IzPu8kAuaZgMwK/IfzMhadMR4pZcwvekBAH4R+R4XZ604YnxNYiBfbP4BAE9nf4fzQhuOGF+SGMaXm78LwLzsexkRqjxifH58LN+IdgPg9zn/zgDbfcT4i/FJfC/aUlrv59xPD6s9Yvyp+FTujfYAYF3OD8m2+BHjc2LT+X6sG9lEWZf7I472YOzT3BfLpwcHeT/3gWPG/zX6OR6K5zDAavh9zoPHjL+4rpafx7MYYVuZl/PQMeNPrU/wVNyZYOv4Ys7Dx4w/tj6PlxJRpoaW8YXsnx0z/uMNvfhdooEZoXe5MfLoR48v9bN4uddVHVLo1t4bXJhZIfAW8C/u/vRRYy8A97r771s/fw24y92XnGh9FRUVrjNFJVk8Eadufw2H9u6ibn81jQdqiB6qYWO3Sey0UvL3rGB85S8JR2uJxOrIjteRm6jlW5G/ZVHzEKZHX+O+8Kxj1nt50/dY5YP5QtYr/HPk8Y8eT7jRSDbXZ/2QPdllXOOvcF30OeIWJmYR4hYhHorwUO/vEM3uxuS6NxhX/zaJUAQPZeOhCJ4V4a3yr2DhCGfvf5u+datxy8JCWWBZeCjMqkFfIGRG2b5FFDdWQuuYhbJIZOWws/90skJG9/0ryWveSygUwkORlvfhXGpLxxMyo/DAesKxWjAjZCHMDI/k0dRzJCGD3IObyYo3YqGWMQuFIJxPonggZkakdjshjxEywyyEhQyL5EFBb0IG1lBDCCdkoZZlQiEsnIPldiNkQMO+w76rrfPcrAhkF7R83HgAMAz70zQ4FIFIXst0PFp3zM/GsiIQzmkZjzUcu/5QuGUb7hBvPmzY/riClu+nOyRifxr6aDzU8ubOEX86tK6/Jasds9qjUhw2bkeMhUJHL9E+ZrbE3SuOO9aeQjezCPA8MM/df3ic8YeBN919buvna4FpJ9vlokKXtrg7B+ub2VXbzO7d1WRteIX4gSpCh3YQadhFQVMNvwhfw7zoOEY0LuXJ8D3HrONLzXcwLzGJi8Or+V74ZzSE8mkMFdAcLiCaVcj8PjdRV3w25b6d4XVLCOcWEs4pIJJbQDgnn1i/cWTnF5Pv9eTTQG5eITl5BeTk5LWUnkgnO6NCt5b/Vp4A9rr7HSdY5grgy8DltLwY+oC7TzrZelXoAlDfFGXrvgYqd+0hb+WvsP1byKndRnHjdnrHd/Hj2NX8LH4l5baL+Tl3tnwNOeyxXhyIlPB6z+vZ0ftiysKHmHDoTUKFJWQXlZLXvZSC7r0p6NmPosICcsJZAT9TkeQ4WaG3Zx/6hcBNwHIzW9r62DeBcgB3nwW8SEuZbwDqgVvPNLSkl/qmKNtXLWDflhXEdq0mb/96Sho380J0It+P3UgOzazN/T6NHqE6qw8HcvuztmAC4wZ8nAcGj6dPQRaVPpGefcvJL+pBPjAQGHPEVi4M5LmJdBXtOcrl9xy7O+joZRy4PVmhJLU1HNrH1pULOPjhIrYech5u+AQbqmtZmP3XDLODNHsWO7LK2F0wnCH9J/HjUeMp75nP/pyVFJf0ozx0otl0n059HiKpJrDL50r62FPbxKLNe8n7w78ydNfLDExUMqJ1zG0sAwZdwYwx/dgYfpCG/uWUDT6HQdk5DDpmTd07N7hImlGhyyk7sHMTWxY+i2+cT8GhjVxS/8+A8e3sXRTmDWBz7yvJHzyRAaOmcH7fgUz66NX94UHGFkl7KnRpUzzhLN9+gG1v/5rz1v2Y8vgWzgV20YNNBeP4x48NZPywcsb2v4zssI78EAmKCl2OK9bcyNoFz9Ow7Gl+eGAab9f1Z2poN+UFPdg08CpKxl3JiDEV9AlnMSXosCICqNDlMJ5IsHrhPOre/QUj9r3JaOo45Hl8st8EPvfnV3DxsE/Rs+AbQccUkRNQoQs79h7gN0ureX7xen5TdwtOiFXFU8ka8xlGXXQVt+XnBx1RRNpBhZ6hPJFgxcKXafrdg+TWbuXfmv+FKUN7sWjCo0yaMpVJhcVBRxSRU6RCzzBNzU28/+Jj9Fz+CGPjGzhAIWsHfIb5V19EeW8dNiiSylToGaIpFue/F1fy4auP8p3Y/WwL9WfJmG8x+rKZTCroFnQ8EUkCFXqai0ajLHr2p8xbs5snaiczqfwSlp8zhjEfv4aBJzwjU0RSkQo9jS1967d0e+tuPpbYQiR7Epfc9hUuOrvkiMt4ikj6UKGnoc1rl7Hvt3cxvvEdqqwPyy64n4pP3azLvYqkORV6GmmKxXnwjQ9Z+dYL/Ci8jIVn38H4a79OWa4OOxTJBCr0NLHm3VeY9/qrPLB/KlePu4zop2YyuVfyb3ElIl2XCj3FNTfW8/7jdzJ5168osH6cd9OXmTZ6YNCxRCQAKvQUtm3te8T++1YmxzezoNf/Yewt/8G0Ih1LLpKpVOgp6rkFK/izly6n2SIsuehhLrjk+qAjiUjAVOgpJhqLcc8La/j5gi3c0e9ObrjueiaWHXurCBHJPCr0FLJn+0b2zrmeyro/Z+bUa/nypZcRztKhiCLSQoWeIjYte4vi395EP2/mSxcPZvJl5wQdSUS6GBV6Clj95q8Z9Mbt7LPu7LnuaSaPqQg6koh0Qfp7vYt7c/7rDHtjJpXhgWT91asMU5mLyAmo0LuwOX/YxC0v1vN48e30+eqr9O1fHnQkEenCtMuli3rnye/y5Iq+XDp6Ijdd/11yI7oyooicnGboXdCiOXcxZf0P+Uafd/nJjRNU5iLSLir0LubdJ77B+Zsf5p1uM5h6+ywiOixRRNpJu1y6kMVP3cekTQ+xsNt0Kr76JOGwfjwi0n6a/nURLy2vovGDZ3g/dwrjv6wyF5FTp9boAhZ8uIev/moZ48r+mTm3VJCdnR10JBFJQZqhB2zb+g9o/MVnObdHlNm3Xkh+QVHQkUQkRWmGHqAD+2rgPz/HOGp54NoRdM/XzFxETl+bM3Qze8zMqs1sxQnGi83sf8xsmZmtNLNbkx8z/cSizWyd9Vn6JHax49LZlA0eEXQkEUlx7dnlMgeYcZLx24FV7n4eMA34dzPTVLMNix/5CmOb3mPpud9m1AWXBR1HRNJAm4Xu7vOBvSdbBCgyMwMKW5eNJSdeenp16QbKdrzGwtJrmXTNHUHHEZE0kYx96D8BngOqgCLgc+6eON6CZjYTmAlQXp6Z1yXZtreev3nmQ0aX/IQnbvt40HFEJI0k4yiXS4GlQBkwDviJmXU73oLuPtvdK9y9orS0NAmbTi3NTY288sg/EibKDz4/lezcvKAjiUgaSUah3wo87S02AJuAkUlYb9pZ8tid/EX9o8y+qJ7yXvlBxxGRNJOMQt8KfBLAzPoAI4CNSVhvWlnx9gtM3jmXd3tdTcUlnw06joikoTb3oZvZXFqOXikxs0rgbiAC4O6zgHuAOWa2HDDg6+6+u8MSp6Dag/vo8cqd7Aj1Ycyt9wcdR0TSVJuF7u43tDFeBUxPWqI0tPyJO5mcqGbdFf9F/8LuQccRkTSlU/872Jtrq/l21QW8MuTvGDnp0qDjiEga06n/HaihKco/PrOC3NKRTPvCXwYdR0TSnAq9Ay2d8zf8fe0G+n7xCXLCuuuQiHQs7XLpIJtWLaKi6knKehUz+ezeQccRkQygQu8AiXicpt9+lVrL5+zP/0fQcUQkQ6jQO8CS/5nFyOgq1p97Fz1K+wUdR0QyhAo9yeqbovRa9hBrw8OpuOr2oOOISAZRoSfZw/M3cV3D/6P5yocIZemFUBHpPCr0JNpVs4fZ89czZexIxo47P+g4IpJhdNhiElX+8ks8btvpP+OVoKOISAbSDD1JNq1YwMQDr5AYcD4DexUGHUdEMpAKPUkOvvgdDlLA6Gu/HXQUEclQKvQkWL/kdc6rf4cVg75Icc+SoOOISIbSPvQkqHntx/SkmLHX3BV0FBHJYJqhn6F3N+3l1r0380bFLIq69Qg6johkMM3Qz9D9L6+mW1ERV0z/RNBRRCTDaYZ+Bta+O48fVN3MP4yPkZetk4hEJFgq9DPQ/Ma/kW/NXDr1Y0FHERFRoZ+uzSsWMLbhXVaVf4HCwm5BxxERUaGfrn3zfkCt5zHmqr8JOoqICKBCPy1Vm1Zz3sE3WdbvWrr3Kg06jogIoKNcTsvPlsfZHv877vn0zUFHERH5iGbop+hQY5RfL9lO/pgr6FNWHnQcEZGPaIZ+ipY/+yNujy/jYxfcH3QUEZEjqNBPQTwWZeiah+mW15cxg3oFHUdE5Aja5XIKVr4+l75eQ8OEvwo6iojIMVTopyB78cNU0Ztxl9wYdBQRkWOo0Ntpy8qFjGxewaahNxKJRIKOIyJyDO1Db6fnV+2hLHExH7/s/wYdRUTkuDRDb4fGaJzZq8K8NvKf6FnaN+g4IiLH1Wahm9ljZlZtZitOssw0M1tqZivN7K3kRgzewvnz6Nv4ITdO0nHnItJ1tWeGPgeYcaJBM+sOPAR82t1HA9clJ1rX0eede/hZ7gNMGdIz6CgiIifUZqG7+3xg70kWuRF42t23ti5fnaRsXcLWNUsYGV1F5dDPEcrSHioR6bqS0VDDgR5m9qaZLTGzE17gxMxmmtliM1tcU1OThE13vB2vz6LZsxg+Xceei0jXloxCDwMTgSuAS4Fvmdnw4y3o7rPdvcLdK0pLu/5VCpubGhlR/SIfFF1MSZ/+QccRETmpZBR6JfCSu9e5+25gPnBeEtYbuPcW/YFsjxKe8Pmgo4iItCkZhf4scLGZhc0sH5gMrE7CegP3xObuTM96hNEXXx10FBGRNrV5YpGZzQWmASVmVgncDUQA3H2Wu682s5eAD4AE8Ii7n/AQx1RxoK6J11ZXc+Pks4hEsoOOIyLSpjYL3d1vaMcy9wH3JSVRF7HmxZ/wTNYT+Khng44iItIuOvX/BLqt+w354TjlQwcFHUVEpF10YPVxbN+4hnOiK6kadBUW0rdIRFKD2uo4trz5OABDPnFLsEFERE6BCv04+lW+yKrsMfQtP+7h9CIiXZIK/Sjrdh7gJ42Xs2PMl4KOIiJySlToR3lh+S6e9qmM/cRng44iInJKVOhHiS75JdMHOr2LcoOOIiJySlToh9m8Zil3Nd7PbT2WBR1FROSUqdAPU/X2XACGTm3zXCoRkS5HhX6YPpXzWBMZRUn/oUFHERE5ZSr0VlvWLeOsxCYODr0i6CgiIqdFhd5q/eLXibsxRLtbRCRFqdBb/XjfJG4u+RWl/c8KOoqIyGlRoQPVBxtZtm0/F4xWmYtI6lKhAx++9jg/j9zL9KG67rmIpC5dPhfIXv88Z2VVUVo+MOgoIiKnLeNn6A31dYysW8SWkqm6VK6IpLSMb7DVC16kwJrIH3Nl0FFERM5Ixhd608oXqPcchk25POgoIiJnJKMLPZFw3tjfm9/1upbs3Pyg44iInJGMLvTl2w8wu/7j1F/8zaCjiIicsYwu9KXL3qeABi4eVhp0FBGRM5bRhy2O/+A7PFdwkJLCa4OOIiJyxjJ2hn7w4H5GNK1gT+8pQUcREUmKjC30dQvnkWMxikZfGnQUEZGkyNhCb177Mo0e4ayJnwo6iohIUmRkobs7ZXsWsCF/HNl5BUHHERFJiows9M176vnrxq+w5bw7g44iIpI0GVno89fVsMbLGXP+tKCjiIgkTUYWemjxo3y2eDWDeml3i4ikj4w7Dj0ai/HpPY9yTq9pQUcREUmqNmfoZvaYmVWb2Yo2ljvfzOJm1qXP0tmwfAHFVkfW0GlBRxERSar27HKZA8w42QJmlgX8AJiXhEwdau+K1wAYNHF6wElERJKrzUJ39/nA3jYW+wrwG6A6GaE6Ut72BVSGyujZb3DQUUREkuqMXxQ1s/7AZ4BZ7Vh2ppktNrPFNTU1Z7rpU9YcjZPfUMXOHhWdvm0RkY6WjKNcfgR83d3jbS3o7rPdvcLdK0pLO/8Kh8urDjCj6V72Tr2n07ctItLRknGUSwXwKzMDKAEuN7OYuz+ThHUn1YIP9wBGxdllQUcREUm6My50dx/yx4/NbA7wfFcsc4Axi7/JD4qL6FlwRdBRRESSrs1CN7O5wDSgxMwqgbuBCIC7t7nfvKtoam6iou53rCk96QE7IiIpq81Cd/cb2rsyd7/ljNJ0oA1Lf89oayB89tSgo4iIdIiMOfV//6rXARg6UTN0EUlPGVPoBTvfZWtoIN1K9YKoiKSnjCj0WDzBwob+rOtzWdBRREQ6TEYU+pqdh7i36TrqJt8RdBQRkQ6TEYW+fMMWsohTMbhn0FFERDpMRlw+96wl9/Bm7geUFa8JOoqISIfJiBl6/4PL2FM4jNazWUVE0lLaF/rO7Vvozy6a+50fdBQRkQ6V9oW+bdkbAPQ8RycUiUh6S/tCj256m0aPMHjMBUFHERHpUGn/ouhTTeezokc/ZmbnBh1FRKRDpfUMvbYpxjM1ZdSOujHoKCIiHS6tC331quVcYMupGFgQdBQRkQ6X1oUeXfYUT2bfy/i+kaCjiIh0uLQu9NzqpVRaP4p69Ak6iohIh0vbQnd3yupXs6todNBRREQ6RdoW+q7tm+nLHuJlE4KOIiLSKdK20Lev/AMAPc6eHHASEZHOkbaF/mrsXD4T/R7lOqFIRDJE2hb6+9vrSPQ7j5xcHbIoIpkhLQs9Ho8zffuDXN6zKugoIiKdJi0Lfdv65fyF/Q8T83YFHUVEpNOkZaHvWtPygmjvcz4WcBIRkc6TloWeqFxCnecy4Ozzgo4iItJp0rLQe+5fzpbc4YTCaX8xSRGRj6RdoTc2RymI7uVQT83ORSSzpF2hr91Vx0VN97Nvyt8HHUVEpFOlXaGvrDoIGKMHlgYdRUSkU6VdoZe8/wD35T7GgB55QUcREelUafeqYfnu35HIjmBmQUcREelUbc7QzewxM6s2sxUnGP+8mX3Q+va2mQX2amQsGmVQdCOHuo8KKoKISGDas8tlDjDjJOObgI+7+7nAPcDsJOQ6LdvWf0CeNZPVX0e4iEjmabPQ3X0+sPck42+7+77WT98BBiQp2ynbvWERACXDJgUVQUQkMMneh34b8P9PNGhmM4GZAOXl5UneNGzd30y2n8XoYZqhi0jmSVqhm9knaCn0i060jLvPpnWXTEVFhSdr23/068bzaeg9kWcj2cletYhIl5eUwxbN7FzgEeAqd9+TjHWeKk8kWFl1gDFl3YLYvIhI4M640M2sHHgauMnd1515pNNTtWU9f/BbmZ61JKgIIiKBanOXi5nNBaYBJWZWCdwNRADcfRbwbaAX8FDrsd8xd6/oqMAnsmvtO/S3evoNGNzZmxYR6RLaLHR3v6GN8b8E/jJpiU5T07alxDxE+chO/79ERKRLSJtT//P3rmBb1kBy8wuDjiIiEoi0KfR+DRvYUzg86BgiIoFJi0Lfd6iBX8cuYu+gS4OOIiISmLQo9DXV9dwXu56csVcHHUVEJDBpUehbtm4mn0ZG9i0KOoqISGDSotCHLP8Rf8j9Gr0LdYaoiGSutCj04oPrqcoejIXS4umIiJyWlG/ARDzOgOhmarvpCBcRyWwpX+g7t66n0Bqgz+igo4iIBCrlC716w3sAFA/WJXNFJLOlfKEviw7gW9FbGKBT/kUkw6V8oS/aX8gb3a6isKh70FFERAKV8oVeVPkWF5Q0Bh1DRCRwKV3oTY313FP3T1yTmBd0FBGRwKV0oVeu/4CwJYiUjQk6iohI4FK60Pdteh+AkqETAk4iIhK8lC706I4VNHuYsrM0QxcRSelCz9u/ge1ZA4hk5wQdRUQkcG3egq4ru9dvZcIA5+tBBxER6QJSdobeGI3z7oEicsonBh1FRKRLSNlC37ppHTeH5jGqm45BFxGBFC70g+t/z3cjTzCsoCHoKCIiXULKFnpsx2ribpSdNTboKCIiXULKFnr2/vXsCPUlJzc/6CgiIl1CyhZ6z/rN1OQNCTqGiEiXkZKFHotG6RffQWPx2UFHERHpMlKy0Lfub2J808NUn/uloKOIiHQZKVno66trqSeXQQMGBB1FRKTLSMlC95XP8PXwXM4qyQs6iohIl5GSp/6XVL7K+PB7FOXpGi4iIn+UkjP04vpNVOcMCjqGiEiX0mahm9ljZlZtZitOMG5m9oCZbTCzD8ysQy9OnojH6R/dRl23szpyMyIiKac9M/Q5wIyTjF8GDGt9mwn89MxjnVj19o3kWxNWOqIjNyMiknLaLHR3nw/sPckiVwE/9xbvAN3NrF+yAh6tqnIT+72AwgGjO2oTIiIpKRn70PsD2w77vLL1sWOY2UwzW2xmi2tqak5rY4myCv5uyLP0Hftnp/X1IiLpKhmFbsd5zI+3oLvPdvcKd68oLS09rY1VDO7JI7ecT6+i3NP6ehGRdJWMQq8EBh72+QCgKgnrFRGRU5CMQn8OuLn1aJcpwAF335GE9YqIyClo88QiM5sLTANKzKwSuBuIALj7LOBF4HJgA1AP3NpRYUVE5MTaLHR3v6GNcQduT1oiERE5LSl5pqiIiBxLhS4ikiZU6CIiaUKFLiKSJqzlNc0ANmxWA2w5zS8vAXYnMU4q0HPODHrOmeFMnvMgdz/umZmBFfqZMLPF7l4RdI7OpOecGfScM0NHPWftchERSRMqdBGRNJGqhT476AAB0HPODHrOmaFDnnNK7kMXEZFjpeoMXUREjqJCFxFJEylX6GY2w8zWtt6U+h+CztPRzGygmb1hZqvNbKWZfS3oTJ3BzLLM7H0zez7oLJ3FzLqb2VNmtqb1531B0Jk6kpnd2fo7vcLM5ppZWt61xsweM7NqM1tx2GM9zewVM1vf+r5HMraVUoVuZlnAg7TcmHoUcIOZjQo2VYeLAX/r7ucAU4DbM+A5A3wNWB10iE52P/CSu48EziONn7+Z9Qe+ClS4+xggC7g+2FQdZg4w46jH/gF4zd2HAa+1fn7GUqrQgUnABnff6O7NwK9ouUl12nL3He7+XuvHh2j5R37ce7amCzMbAFwBPBJ0ls5iZt2AqcCjAO7e7O77g03V4cJAnpmFgXzS9E5n7j4f2HvUw1cBT7R+/ARwdTK2lWqF3u4bUqcjMxsMjAcWBpukw/0IuAtIBB2kEw0FaoDHW3c1PWJmBUGH6ijuvh34N2ArsIOWO529HGyqTtXnj3d2a33fOxkrTbVCb/cNqdONmRUCvwHucPeDQefpKGZ2JVDt7kuCztLJwsAE4KfuPh6oI0l/hndFrfuMrwKGAGVAgZl9IdhUqS/VCj0jb0htZhFayvxJd3866Dwd7ELg02a2mZZdan9mZr8MNlKnqAQq3f2Pf309RUvBp6tLgE3uXuPuUeBp4GMBZ+pMu8ysH0Dr++pkrDTVCn0RMMzMhphZNi0vojwXcKYOZWZGy37V1e7+w6DzdDR3/4a7D3D3wbT8fF9397Sfubn7TmCbmY1ofeiTwKoAI3W0rcAUM8tv/R3/JGn8IvBxPAd8sfXjLwLPJmOlbd5TtCtx95iZfRmYR8ur4o+5+8qAY3W0C4GbgOVmtrT1sW+6+4sBZpKO8RXgydbJykbS+Ibr7r7QzJ4C3qPlSK73SdNLAJjZXGAaUGJmlcDdwPeB/zaz22j5z+26pGxLp/6LiKSHVNvlIiIiJ6BCFxFJEyp0EZE0oUIXEUkTKnQRkTShQhcRSRMqdBGRNPG/Ck2AqfNAND0AAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(tsmooth, sol.y.T)\n", "plt.plot(tsmooth, hanalytic, '--')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can see that this interpolation is very close to the correct solution." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a problem with taking big steps if inputs change discontinuously. This example illustrates the problem:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": {}, "outputs": [], "source": [ "import scipy.integrate" ] }, { "cell_type": "code", "execution_count": 61, "metadata": {}, "outputs": [], "source": [ "def Fin(t):\n", " \"\"\" A step which starts at t=2 \"\"\"\n", " if t < 2:\n", " return 1\n", " else:\n", " return 2" ] }, { "cell_type": "code", "execution_count": 62, "metadata": {}, "outputs": [], "source": [ "def dhdt(t, h):\n", " Fout = K*h\n", " return 1/A*(Fin(t) - Fout)" ] }, { "cell_type": "code", "execution_count": 63, "metadata": {}, "outputs": [], "source": [ "tspan = (0, 10)" ] }, { "cell_type": "code", "execution_count": 64, "metadata": {}, "outputs": [], "source": [ "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0])\n", "smoothsol = scipy.integrate.solve_ivp(dhdt, tspan, [h0], t_eval=tsmooth)" ] }, { "cell_type": "code", "execution_count": 65, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 65, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(sol.t, sol.y.T, 'o')\n", "plt.plot(smoothsol.t, smoothsol.y.T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "That downward bump in the level is a numerical anomaly due to the places where the samples are taking during integration. To make sure that we don't miss the moment when the step occurs, we can limit the step size that `solve_ivp` uses." ] }, { "cell_type": "code", "execution_count": 66, "metadata": {}, "outputs": [], "source": [ "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0], max_step=0.1)\n", "smoothsol = scipy.integrate.solve_ivp(dhdt, tspan, [h0], t_eval=tsmooth, max_step=0.1)" ] }, { "cell_type": "code", "execution_count": 67, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 67, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(sol.t, sol.y.T, 'o')\n", "plt.plot(smoothsol.t, smoothsol.y.T)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This works, but we pay for this with computer time:" ] }, { "cell_type": "code", "execution_count": 68, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.25 ms ± 207 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%%timeit\n", "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0])" ] }, { "cell_type": "code", "execution_count": 69, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "19.5 ms ± 266 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" ] } ], "source": [ "%%timeit\n", "sol = scipy.integrate.solve_ivp(dhdt, tspan, [h0], max_step=0.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A note about odeint\n", "\n", "The default solver for ODEs in scipy used to be odeint, but this is now officially deprecated. You may still encounter it in older codes, so take note of the differences:" ] }, { "cell_type": "code", "execution_count": 70, "metadata": {}, "outputs": [], "source": [ "def odeintdhdt(h, t):\n", " \"\"\"Odeint expects a function with the arguments reversed from solve_ivp\"\"\"\n", " return dhdt(t, h)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The order in which the initial values and the input times are specified is different. Also, unlike `solve_ivp`, you always give `odeint` the times you want the results at." ] }, { "cell_type": "code", "execution_count": 71, "metadata": {}, "outputs": [], "source": [ "odeinth = scipy.integrate.odeint(odeintdhdt, h0, tsmooth)" ] }, { "cell_type": "code", "execution_count": 72, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[]" ] }, "execution_count": 72, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.plot(sol.t, sol.y.T, 'o')\n", "plt.plot(tsmooth, odeinth)" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }